
#include <stdio.h>
#include "main.h"
#include "debug.h"
#include "trace.h"
#include "main_container.h"
#include "fatal_errors.h"
#include "error_report.h"
#include "flag_checker.h"
#include "file_loader.h"
#include "syntax_tree.h"
#include "syntax_parser.h"
#include "semantic_analyzer.h"


#include "semantic/main2.h"



MainContainer * CompilerData = NULL;


int main (int argc, char ** argv) {
#ifdef TRACE
	// Start trace info logging object.
	Trace *LogTrace = NULL;
	try	{
		LogTrace = new Trace();
	}
	catch(...)	{
		ReportCompilerInternalError(ICE_ALLOC_LOG_TRACE);
	}
#endif

#ifdef DEBUG
	// Start debug info logging object.
	Debug *LogDebug = NULL;
	try	{
		LogDebug = new Debug();
	}
	catch(...)	{
		ReportCompilerInternalError(ICE_ALLOC_LOG_DEBUG);
	}
#endif

	// Start global object - main container (data about the compilaton process).
	try	{
		CompilerData = new MainContainer();
	}
	catch(...)	{
		ReportCompilerInternalError(ICE_ALLOC_MAIN_CONTAINER);
	}

#ifdef TRACE
	CompilerData->LogTrace = LogTrace;
#endif

#ifdef DEBUG
	CompilerData->LogDebug = LogDebug;
#endif

	// Start error and warning report object.
	ErrorReport * errorReport = NULL;
	try	{
		errorReport = new ErrorReport();
		errorReport->InitializeErrorsTable();
		errorReport->InitializeWarningsTable();
	}
	catch(...)	{
		ReportCompilerInternalError(ICE_ALLOC_ERROR_REPORT);
	}
	CompilerData->ErrorWarningReport = errorReport;
	// Start flag checker.
	FlagChecker * flagChecker = NULL;
	try	{
		flagChecker = new FlagChecker();
	}
	catch(...)	{
		ReportCompilerInternalError(ICE_ALLOC_FLAG_CHECKER);
	}
	CompilerData->Flags = flagChecker;
	// Parse arguments given to the compiler.
	try	{
		CompilerData->Flags->ProcessArguments(argc, argv);
	}
	catch(...)	{
		ReportCompilerInternalError(ICE_PARSING_ARGUMENTS_FAILED);
	}
	// Start file loader.
	FileLoader * fileLoader = NULL;
	try	{
		fileLoader = new FileLoader();
	}
	catch(...)	{
		ReportCompilerInternalError(ICE_ALLOC_FILE_LOADER);
	}
	CompilerData->Loader = fileLoader;
	// Load source gpss files to memory.
	try	{
		CompilerData->LoadedFiles = new GenericTable <LoadedFile>();
		CompilerData->Loader->LoadFiles();
	}
	catch(...)	{
		ReportCompilerInternalError(ICE_LOADING_FILES);
	}

#ifdef DEBUG
	try	{
		CompilerData->LogDebug->PrintLoadedFiles(CompilerData->LoadedFiles);
	}
	catch(...)	{
		ReportCompilerInternalError(ICE_DEBUG_OUTPUT_LOADED_FILES);
	}
#endif

	// Initialize lexic unit tables
	try	{
		CompilerData->Units = new LexicUnits();
		CompilerData->Lexic = new LexicAnalyzer();
	}
	catch(...)	{
		ReportCompilerInternalError(ICE_ALLOC_LEXIC_ANALYZER);
	}
	// Run lexic analysis
	try
	{
		if(!CompilerData->Lexic->LexicAnalysis())
		{
			throw exception();
		}
	}
	catch(...)
	{
		ReportCompilerInternalError(ICE_LEXIC_ANALYSIS_FAILURE);
	}

#ifdef DEBUG
	// debug output of lexic analysis results
	try
	{
		CompilerData->LogDebug->OutputLexicToXML(CompilerData->Units);
	}
	catch(...)
	{
		ReportCompilerInternalError(ICE_LEXIC_ANALYSIS_DEBUG_OUTPUT_FAILURE);
	}
#endif

	// syntax analysis ... memory allocation
	try
	{
		CompilerData->SyntaxParser = new Parser();
		CompilerData->SyntaxTree = new AbstractSyntaxTree();
	}
	catch(...)
	{
		ReportCompilerInternalError(ICE_ALLOC_SYNTAX_PARSER);
	}

	// syntax analysis
	try
	{
		CompilerData->SyntaxParser->StartParsing();
	}
	catch(...)
	{
		ReportCompilerInternalError(ICE_SYNTAX_ANALYSIS_FAILURE);
	}


	// syntax parsing ... attact parents to children
	try
	{
		CompilerData->SyntaxTree->AttachParentsToChildren();
	}
	catch(...)
	{
		ReportCompilerInternalError(ICE_SYNTAX_PARENTS_CHILDREN_CONNECTIONS);
	}

#ifdef DEBUG
	// output syntax tree to XML
	try
	{
		CompilerData->LogDebug->OutputSyntaxToXML(CompilerData->SyntaxTree, CompilerData->Units);
	}
	catch(...)
	{
		ReportCompilerInternalError(ICE_SYNTAX_ANALYSIS_DEBUG_OUTPUT_FAILURE);
	}
#endif




	// novi kod
	main2();






	// stari kod

/********************************************************************
	// semantic analysis... taking memory
	try
	{
		CompilerData->Semantics = new SemanticAnalyzer();
	}
	catch(...)
	{
		ReportCompilerInternalError(ICE_ALLOC_SEMANTIC_ANALYZER);
	}


	// semantic analysis... reorganize  for verification
	try
	{
		CompilerData->Semantics->Gather();
	}
	catch(...)
	{
		ReportCompilerInternalError(ICE_SEMANTICS_REORGANIZATION);
	}


#ifdef DEBUG
	// output semantic structures to XML
	try
	{
		CompilerData->LogDebug->OutputSemanticsStructuresToXML(CompilerData->Semantics, CompilerData->Units);
	}
	catch(...)
	{
		ReportCompilerInternalError(ICE_SEMANTIC_STRUCTURES_DEBUG_OUTPUT_FAILURE);
	}
#endif


	// semantic analysis... flatten hierarchy
	try
	{
		CompilerData->Semantics->FlattenHierarchy();
	}
	catch(...)
	{
		ReportCompilerInternalError(ICE_SEMANTICS_FLATTEN_HIERARCHY);
	}


	// semantic analysis... fill names appropriatelly
	try
	{
		CompilerData->Semantics->FillNames();
	}
	catch(...)
	{
		ReportCompilerInternalError(ICE_SEMANTICS_FILL_NAMES);
	}


#ifdef DEBUG
	// output semantic structures to XML
	try
	{
		CompilerData->LogDebug->OutputSemanticsStructuresFlattenToXML(CompilerData->Semantics, CompilerData->Units);
	}
	catch(...)
	{
		ReportCompilerInternalError(ICE_SEMANTIC_STRUCTURES_FLATTEN_DEBUG_OUTPUT_FAILURE);
	}
#endif


	// gather all names and remove contexts TODO




	// semantic analysis... real semantic verification
	try
	{
		CompilerData->Semantics->Verify();
	}
	catch(...)
	{
		ReportCompilerInternalError(ICE_SEMANTICS_VERIFICATION);
	}



	// code generation
	try
	{
		CompilerData->Semantics->GenerateCode();
	}
	catch(...)
	{
		ReportCompilerInternalError(ICE_CODE_GENERATION);
	}
**********************************************************************/

	return 0;
}
